/******************************************
 *Author:庄育龙
 *Function:主窗口各部件功能实现，包括按钮、菜单及其事件等
 *Created Date:2013.05.02
 *Last Modified:2013.05.29
 ******************************************/

#include <QMessageBox>
#include <QSettings>
#include <QTextCodec>
#include <QApplication>
#include <QPainter>
//以上为Qt自带库

#include "dialog.h"
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "data.h"
#include "regret.h"
#include "networkd.h"
#include "win.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    IsRun=false;//标识游戏尚未开始，令ChessWidget对象不响应鼠标事件
    ui->setupUi(this);

    ui->label->hide();
    ui->label_2->hide();
    ui->label_3->hide();
    //隐藏以上3个label


    QPalette magenta;
    magenta.setColor(QPalette::WindowText,Qt::magenta);
    ui->label_3->setPalette(magenta);
    //用来改变label_3的颜色


    udpSocket = new QUdpSocket(this);
    int port;
    port = 45455;
    udpSocket->bind(port,QUdpSocket::ShareAddress
                    | QUdpSocket::ReuseAddressHint);
    //声明UDP Socket及端口

    /*进行信号和槽的连接*/
    connect(udpSocket,SIGNAL(readyRead()),this,SLOT(processPendingDatagrams()));
    //UDP Socket可以读取数据时通知槽processPendingDatagrams()以读取UDP数据报
    connect(ui->widget,SIGNAL(send(bool)),this,SLOT(ChangeColor(bool)));
    //用以标识当前轮到谁下棋，以红色突出显示
    connect(this,SIGNAL(send(bool)),this,SLOT(ChangeColor(bool)));
    //同上
    connect(ui->widget,SIGNAL(additem(int,int,int)),this,SLOT(AddItem(int,int,int)));
    //用以向listwidget对象添加项目
    connect(this,SIGNAL(additem(int,int,int)),this,SLOT(AddItem(int,int,int)));
    //同上
    connect(this,SIGNAL(win(int,bool)),this,SLOT(WinNotify(int,bool)));
    //通过发出win(int,bool)信号在游戏结束时弹出提示
    connect(ui->widget,SIGNAL(win(int,bool)),this,SLOT(WinNotify(int,bool)));
    //同上
    connect(ui->widget,SIGNAL(newpoint(int,int)),this,SLOT(newpoint(int,int)));
    //在局域网游戏时把鼠标点击对应的坐标位置提供给newpoint(int,int)槽以发送UDP数据报
    connect(&cmd1,SIGNAL(readyRead()),ui->widget,SLOT(Connect()));
    //当调用困难AI时，如果可以读取数据则调用Connect()槽读取数据并下子

}

MainWindow::~MainWindow()
{
    //if(lan) sendMessage(Left,0,0);//在局域网游戏进行中退出则发送Left信号提醒对方
    delete ui;
}


void MainWindow::on_action_4_triggered()//弹出设置对话框
{
    Dialog dialog;//新建一个Dialog对象
    dialog.exec();//运行dialog

}

void MainWindow::on_action_3_triggered()//用来弹出关于对话框
{
    QMessageBox::about(NULL, "关于", "<p align='center' ><span style=' font-size:11pt; color:#000000;'>该程序由北京大学地球与空间科学学院</span></p>\n<p align='center' ><span style=' font-size:11pt; color:#000000;'>12级 数据结构与算法课 第14组完成</span></p>\n\n<p align='center'><span style=' font-size:11pt; color:#000000;'>成员:</span></p>\n<p align='center' ><span style=' font-size:11pt; color:#ff0000;'>庄育龙</span></p>\n<p align='center' ><span style=' font-size:11pt; color:#ff0000;'>王英杰</span></p>\n<p align='center' ><span style=' font-size:11pt; color:#ff0000;'>周正阳</span></p>\n<p align='center' ><span style=' font-size:11pt; color:#ff0000;'>杨飙</span></p>\n<p align='center' ><span style=' font-size:11pt; color:#ff0000;'>马博文</span></p>\n\n<p align='center' ><span style=' font-size:11pt; color:#000000;'>如有问题建议请发邮箱:</span><a href='mailto:linyizyl@pku.edu.cn'><span style=' font-size:11pt; text-decoration: underline; color:#0000ff;'>linyizyl@pku.edu.cn</span></a></p>\n<p align='center'><span style=' font-size:11pt; color:#000000;'>谢谢支持!</span></p>");
}

void MainWindow::on_pushButton_3_released()//开始
{
    if(lan) {
        sendMessage(Restart,0,0);
        return;
    }
    //如果是局域网那么发出重新开始请求，然后结束该函数
    ClearBoard();//清空棋盘
    ui->listWidget->clear();//清空listwidget列表
    clear();//清空栈

    QString setfile = QApplication::applicationDirPath()+"/settings.ini";
    QSettings settings(setfile, QSettings::IniFormat);
    QByteArray nameBytes=settings.value("Name/Name").toByteArray();
    QTextCodec * codec=QTextCodec::codecForName("UTF8");
    IsHumanFirst=settings.value("First/Human").toBool();
    QString name=codec->toUnicode(nameBytes);
    QByteArray nameBytes2=settings.value("Name/Name2").toByteArray();
    QString name2=codec->toUnicode(nameBytes2);
    //以上几行与on_action_4_triggered()中功能类似，用于从配置文件中读取设置
    if(settings.value("Forbidden/Enable").toInt()) {
        DoForbidden=true;
    }
    else {
        DoForbidden=false;
    }
    if(settings.value("Difficulty/Difficulty").toInt()==1) {
        Difficulty=1;
    }
    else if(settings.value("Difficulty/Difficulty").toInt()==2) {
        Difficulty=2;
    }
    else {
        Difficulty=3;
    }
    if(name[0]!='\0') ui->label_2->setText(name);
    else ui->label_2->setText("玩家");
    //以上十几行通过获取的设置值调整一些游戏的全局变量

    if(ui->radioButton->isChecked()) {
        IsComputer=true;
        ui->label->setText("电脑");
        if(!IsHumanFirst && Difficulty!=3) {
            ChessBoard[7][7]=1;
            AddItem(7,7,3);
            push(7,7,1);
            update();
        }
        IsRun=true;
    }
    else if(ui->radioButton_2->isChecked()) {
        IsComputer=false;
        if(name2[0]!='\0') ui->label->setText(name2);
        else ui->label->setText("玩家2");
        IsRun=true;
        HumanBlack=true;
    }
    else {
        QMessageBox::critical(NULL, "错误", "请选择一种游戏方式（人机对战或者人人对战）！",QMessageBox::Ok|QMessageBox::Cancel,QMessageBox::Ok);
        return;
    }
    //通过radiobutton判断玩家的游戏方式，并设定全局变量

    ui->pushButton->setEnabled(1);
    ui->pushButton_2->setEnabled(1);
    if(ui->pushButton_3->text()=="重新开始") {
        cmd1.close();
    }
    //调用困难AI时重新开始先结束cmd1 process
    ui->pushButton_3->setText(tr("重新开始"));
    ui->action->setText(tr("重新开始"));
    //改变文字为重新开始
    ui->label->show();
    ui->label_2->show();
    QPalette black;
    black.setColor(QPalette::WindowText,Qt::black);
    ui->label_2->setPalette(black);
    ui->label->setPalette(black);
    //重置label为黑色
    if(DoForbidden) ui->label_3->show();
    else ui->label_3->hide();
    //如果开启了禁手就显示label_3以提示
    if(Difficulty==3 && IsComputer) {
        ui->pushButton_2->setEnabled(0);
        cmd1.start("connect.exe");
        cmd1.write("[START]\n");
        if(!IsHumanFirst) {
            cmd1.write("1\n[PUT] -1 -1\n");
        }
        else {
            cmd1.write("2\n");
        }
    }
    //如果调用困难AI的话进行一些初始化操作
    update();
    //通知程序刷新窗口以重绘ChessWidget
}

void MainWindow::ChangeColor(bool Inturn) {//槽，用来标识当前执棋的一方
    QPalette red;
    red.setColor(QPalette::WindowText,Qt::red);
    QPalette black;
    black.setColor(QPalette::WindowText,Qt::black);
    //通过QPalette设定颜色
    if(Inturn) {
        ui->label_2->setPalette(red);
        ui->label->setPalette(black);
    }
    else {
        ui->label->setPalette(red);
        ui->label_2->setPalette(black);
    }
    //通过提供的bool值来设定label和label_2的颜色
}

void MainWindow::AddItem(int x,int y,int who) {//槽，用来添加List中的内容
    int count=ui->listWidget->count();
    QString name;
    if(who==1) {
        name=ui->label_2->text();
    }
    else if(who==2) {
        name=ui->label->text();
    }
    else {
        name="电脑";
    }
    //通过who来标识是电脑、玩家1还是玩家2下的子
    QString newItem;
    if(x==15 && y==15) {

        QString str0="赢了！";
        QTextStream(&newItem) <<"====="<<name<<str0<<"=====";
        QListWidgetItem *newone=new QListWidgetItem(newItem,ui->listWidget) ;
        newone->setTextColor(Qt::red);
        ui->listWidget->insertItem(count,newone);
        ui->listWidget->scrollToBottom();

        IsRun=false;
        ui->pushButton->setText("暂停");
        ui->pushButton->setEnabled(0);
        ui->pushButton_2->setEnabled(0);
        return;
    }
    //通过设定正常下子不可能出现的(15,15)来返回某一方获胜的消息
    if(x==16 && y==16) {
        QString str0="双方闷平";
        QTextStream(&newItem) <<"====="<<str0<<"=====";
        QListWidgetItem *newone=new QListWidgetItem(newItem,ui->listWidget) ;
        newone->setTextColor(Qt::red);
        ui->listWidget->insertItem(count,newone);
        ui->listWidget->scrollToBottom();
        IsRun=false;
        ui->pushButton->setText("暂停");
        ui->pushButton->setEnabled(0);
        ui->pushButton_2->setEnabled(0);
        return;
    }
    //通过设定正常下子不可能出现的(16,16)来返回双方下平的消息
    QString str1="第";
    QString str2="步 ";
    QString str3="下在了(";
    QString str4=")上";
    QTextStream(&newItem) <<str1<<count+1<<str2<<name<<str3<<x+1<<","<<y+1<<str4;
    ui->listWidget->insertItem(count,newItem);
    //向listwidget中插入项目
    ui->listWidget->scrollToBottom();
    //滚动至最底部
}

void MainWindow::on_pushButton_2_clicked()//按下悔棋按钮时的事件
{
    if(lan) {
        sendMessage(Undo,0,0);
        return;
    }
    //如果是局域网那么发出悔棋请求，然后结束该函数

    int count=ui->listWidget->count();//count是listwidget中的项目数
    if(count==0||(count==1&&IsComputer&&!IsHumanFirst)) {
        QMessageBox::critical(NULL, "错误", "您还没下棋呢！怎么悔棋吖咩~",
                              QMessageBox::Ok|QMessageBox::Cancel,QMessageBox::Ok);
        return;
    }
    //如果处于无法悔棋的情况那么拒绝悔棋并弹出对话框提示
    QListWidgetItem *toDel;
    count--;
    toDel=ui->listWidget->takeItem(count);
    delete toDel;
    if(count==0) {
        if(!IsComputer) HumanBlack=false;//调整HumanBlack至true表示轮到人人对战中的黑棋一方
    }
    if(IsComputer) {
        count--;
        toDel=ui->listWidget->takeItem(count);
        delete toDel;
        regret();
    }
    //如果跟电脑下那么一次悔两步棋（因为电脑下棋速度快而且下子位置不变）
    else {
        pop();
        HumanBlack=!HumanBlack;
    }
    //如果跟人下那么一次悔一步
    update();
}

void MainWindow::on_pushButton_clicked()//暂停按钮按下的事件
{

    if(IsRun) {
        IsRun=false;
        ui->pushButton->setText("继续");
    }
    else {
        IsRun=true;
        ui->pushButton->setText("暂停");
    }
    //通过判断IsRun变量来调整按钮文字及效果
}

void MainWindow::WinNotify(int who, bool isban) {
    //游戏结束时的提醒，isban表示是否是因为禁手结束，who表示是哪位玩家取得了胜利
    if(isban) {
        QString notify;
        QString name1=ui->label_2->text();
        QString name2=ui->label->text();
        if(lan) {
            if(IsHumanFirst) notify="诶……"+name1+"下到禁手点上了……\n\n恭喜"+name2+"获胜！\n\n("+name1+"还需提高啊！）";
            else notify="诶……"+name2+"下到禁手点上了……\n\n恭喜"+name1+"获胜！\n\n("+name2+"还需提高啊！）";
        }
        else {
            notify="诶……"+name1+"下到禁手点上了……\n\n恭喜"+name2+"获胜！\n\n("+name1+"还需提高啊！）";
        }
        QMessageBox::information(NULL, "游戏结束",notify,QMessageBox::Ok,QMessageBox::Ok);
    }
    else {
        if(who==3) {
            QString name1=ui->label_2->text();
            QString notify="你居然输给了电脑！\n\n【胜败乃兵家常事，大侠"+name1+"请重新来过吧】";
            QMessageBox::information(NULL, "游戏结束",notify,QMessageBox::Ok,QMessageBox::Ok);
        }
        //who==3时代表电脑取胜
        else if(who==4) {
            QMessageBox::information(NULL, "游戏结束","你们居然闷平了……\n\n（你们到底是有多无聊→_→）",QMessageBox::Ok,QMessageBox::Ok);
        }
        //who==4时表示平局
        else if(who==1) {
            QString name1=ui->label_2->text();
            if(IsComputer) {
                QString notify;
                if(Difficulty==1) notify="恭喜"+name1+"战胜了简单电脑！\n\n再接再厉，来挑战中等电脑吧~";
                else if(Difficulty==2) notify="恭喜"+name1+"战胜了中等电脑！很不错哦~\n\n来尝试挑战下困难电脑吧！";
                else notify="恭喜"+name1+"战胜了困难电脑！\n\n你的实力已经超神了！";
                //Difficulty表示难度，不同难度弹出不同提示
                QMessageBox::information(NULL, "游戏结束",notify,QMessageBox::Ok,QMessageBox::Ok);
            }
            else {
                QString name2=ui->label->text();
                QString notify="恭喜"+name1+"获胜！\n\n"+name2+"还需提高呀~";
                QMessageBox::information(NULL, "游戏结束",notify,QMessageBox::Ok,QMessageBox::Ok);
            }
        }
        //who==1时表示人机对战中人取胜或者人人对战中黑棋取胜
        else {
            QString name1=ui->label_2->text();
            QString name2=ui->label->text();
            QString notify="恭喜"+name2+"获胜！\n\n"+name1+"还需提高呀~";
            QMessageBox::information(NULL, "游戏结束",notify,QMessageBox::Ok,QMessageBox::Ok);
        }
        //who==2时表示人人对战中白旗取胜
    }
    IsRun=false;
    //给IsRun赋值为假，表示游戏结束
    cmd1.close();
}

void MainWindow::on_action_2_triggered()//按下开始局域网游戏时的事件
{
    networkd network;//新建networkd对象
    connect(&network,SIGNAL(newgame(QString,QString,QString,bool,bool,bool)),this,SLOT(NewGame(QString,QString,QString,bool,bool,bool)));
    //连接network对话框中的newgame信号到本对象（MainWindow）中的NewGame槽实现新建游戏
    network.exec();
}

void MainWindow::on_action_triggered()//按下游戏菜单中开始的时间
{
    on_pushButton_3_released();//直接转到按下开始按钮的事件，避免重复代码
}

void MainWindow::NewGame(QString userID, QString myIP, QString yourIP, bool iFirst, bool EnableForbidden, bool AllowUndo) {
    //建立新局域网游戏的槽
    if(myIP==getIP()) {//判断参数中的myIP是否与本机IP相同
        ClearBoard();
        ui->listWidget->clear();
        //清空棋盘和listwidget
        IsRun=iFirst;
        //传来的iFirst表示是否自己先手，而自己先手的话设置IsRun为真表示游戏开始，自己后手就设置IsRun为假
        IsHumanFirst=iFirst;
        //IsHumanFirst在局域网游戏中表示是否是自己先手
        serverIP=yourIP;
        //把对方的IP存起来以供校检
        ui->label->setText(userID);
        //调整label内容为对方的ID
        DoForbidden=EnableForbidden;
        //根据传过来的是否开启禁手决定本地的值
        if(AllowUndo) {
            ui->pushButton_2->setEnabled(1);
        }
        else {
            ui->pushButton_2->setEnabled(0);
        }
        //如果禁止悔棋那么就禁用悔棋按钮
        IsComputer=false;
        //表示不是人机对战
        lan=true;
        //表示是互联网对战
        ui->label->show();
        ui->label_2->show();
        if(DoForbidden) ui->label_3->show();
        //给出必要的提示

        QString setfile = QApplication::applicationDirPath()+"/settings.ini";//设定设置文件路径
        QSettings settings(setfile, QSettings::IniFormat);//设定该设置文件为ini格式
        QByteArray nameBytes=settings.value("Name/Name").toByteArray();//读取Name字段
        QTextCodec * codec=QTextCodec::codecForName("UTF8");
        QString name=codec->toUnicode(nameBytes);
        //转换读取的内容为QString类型
        ui->label_2->setText(name);
        //以上几行用来设定label的内容

        ui->pushButton_3->setText("重新开始");
        ui->pushButton_4->setText("退出局域网游戏");
        //重新设置退出按钮的文字
        ui->radioButton->setEnabled(0);
        ui->radioButton_2->setEnabled(0);
        //不允许选择人机对战、人人对战
    }
}

void MainWindow::processPendingDatagrams()   //接收数据UDP
{
    while(udpSocket->hasPendingDatagrams())
    {
        QByteArray datagram;
        datagram.resize(udpSocket->pendingDatagramSize());
        udpSocket->readDatagram(datagram.data(),datagram.size());
        QDataStream in(&datagram,QIODevice::ReadOnly);
        //定义QDataStream类型的in以接收UDP的流数据
        int messageType;
        in >> messageType;
        QString ipAddress,userID,myIP;
        int x,y;
        switch(messageType)
            //通过判断messageType变量判断是哪种请求
            //每一次接收时都要校检IP地址是否正确
        {
        case NewPoint://对方下子的消息
        {
            in >> ipAddress >> myIP >> x >> y;
            if(myIP==getIP() && ipAddress==serverIP && lan) {
                if(IsHumanFirst) {
                    //IsHumanFirst为真表示我方先手，所以传来的子为白子
                    ChessBoard[x][y]=2;
                    additem(x,y,2);
                    //下的子加入listwidget
                    push(x,y,2);
                    //下的子入栈
                    if(IsWin(x,y,2)==1) {
                        additem(15,15,2);
                        win(2,false);
                        return;
                    }
                    //判断是否获胜
                    else if(IsWin(x,y,2)==2) {
                        additem(16,16,1);
                        win(4,false);
                        return;
                    }
                    //判断是否平局
                    send(true);
                    //标识当前轮到我方下子
                    update();
                }
                else {
                    //IsHumanFirst为假代表传来的子为黑子
                    //代码含义同上
                    ChessBoard[x][y]=1;
                    additem(x,y,2);
                    push(x,y,1);
                    if(DoForbidden && isban(x,y)) {
                        additem(15,15,1);
                        win(1,true);
                        return;
                    }
                    else if(IsWin(x,y,1)==1) {
                        additem(15,15,2);
                        win(2,false);
                        return;
                    }
                    else if(IsWin(x,y,1)==2) {
                        additem(16,16,1);
                        win(4,false);
                        return;
                    }
                    send(true);
                    update();
                }

                IsRun=true;
                //接收消息后允许我方下子
            }
            break;
        }
        case Left:
        {
            //处理对方离开的情况
            in >> ipAddress >> myIP;
            if(myIP==getIP() && ipAddress==serverIP && lan) {
                IsRun=false;
                lan=false;
                QMessageBox::information(NULL, "对不起","对方已经离开！",QMessageBox::Ok,QMessageBox::Ok);
                ui->pushButton_3->setEnabled(0);
                ui->pushButton_2->setEnabled(0);
            }
            break;
        }
        case Undo:
        {
            //处理悔棋请求
            in >> ipAddress >> myIP;
            if(myIP==getIP() && ipAddress==serverIP && lan){
                QString notify="对方想要悔棋，是否同意？";
                if(QMessageBox::question(NULL, "悔棋", notify, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes)==QMessageBox::Yes) {
                    //同意的话执行悔棋操作，一次悔两步
                    int count=ui->listWidget->count();
                    QListWidgetItem *toDel;
                    count--;
                    toDel=ui->listWidget->takeItem(count);
                    delete toDel;
                    count--;
                    toDel=ui->listWidget->takeItem(count);
                    delete toDel;
                    regret();
                    sendMessage(allow,0,0);
                    //返回允许悔棋的消息
                    update();
                }
                else {
                    sendMessage(refuse,0,0);
                    //返回拒绝悔棋的消息
                }
            }
            break;
        }
        case refuse:
        {
            //接收拒绝悔棋的消息
            in >> ipAddress >> myIP;
            if(myIP==getIP() && ipAddress==serverIP && lan) {
                QMessageBox::information(NULL, "对不起","对方拒绝悔棋！",QMessageBox::Ok,QMessageBox::Ok);
            }
            break;
        }
        case allow:
        {
            //接收允许悔棋的消息
            in >> ipAddress >> myIP;
            if(myIP==getIP() && ipAddress==serverIP && lan) {
                //代码同Undo里的情况
                int count=ui->listWidget->count();
                QListWidgetItem *toDel;
                count--;
                toDel=ui->listWidget->takeItem(count);
                delete toDel;
                count--;
                toDel=ui->listWidget->takeItem(count);
                delete toDel;
                regret();
                update();
            }
            break;

        }
        case Restart:
        {
            //接收重新开始的请求
            in >> ipAddress >> myIP;
            if(myIP==getIP() && ipAddress==serverIP && lan) {
                QString notify="对方想要重新开始，是否同意？";
                if(QMessageBox::question(NULL, "重新开始", notify, QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes)==QMessageBox::Yes) {
                    //同意的话返回允许重新开始消息
                    sendMessage(allowrestart,0,0);
                    NewGame(ui->label->text(),myIP,ipAddress,IsHumanFirst,DoForbidden,ui->pushButton_2->isEnabled());
                    //重新初始化游戏
                    update();
                }
                else {
                    //返回拒绝
                    sendMessage(refuserestart,0,0);
                }
            }
            break;
        }
        case allowrestart:
        {
            //接收允许重新开始的消息
            in >> ipAddress >> myIP;
            if(myIP==getIP() && ipAddress==serverIP && lan) {
                NewGame(ui->label->text(),myIP,ipAddress,IsHumanFirst,DoForbidden,ui->pushButton_2->isEnabled());
                update();
            }
            break;
        }
        case refuserestart:
        {
            //接收拒绝重新开始的消息
            in >> ipAddress >> myIP;
            if(myIP==getIP() && ipAddress==serverIP && lan) {
                QMessageBox::information(NULL, "对不起","对方拒绝重新开始！",QMessageBox::Ok,QMessageBox::Ok);
            }
            break;
        }
        }
    }
}


QString MainWindow::getIP()  //用以获取ip地址
{
    QList<QHostAddress> list = QNetworkInterface::allAddresses();
    foreach (QHostAddress address, list)
    {
        if(address.protocol() == QAbstractSocket::IPv4Protocol) //使用IPv4地址
            return address.toString();
    }
    return 0;
}

void  MainWindow::sendMessage(MessageType1 type, int x, int y)  //发送信息
{
    QByteArray data;
    QDataStream out(&data,QIODevice::WriteOnly);
    out << type << getIP();
    //通过流输出UDP数据报
    //所有的情况都需要输出消息类型和本机IP
    switch(type)
    {
    case NewPoint://新下子
    {
        out << serverIP << x << y;
        break;
    }

    case Left://离开
    {
        out << serverIP;
        break;
    }

    case Undo://悔棋
    {
        int count=ui->listWidget->count();
        if(count==0||(count==1&&!IsHumanFirst)) {
            QMessageBox::critical(NULL, "错误", "您还没下棋呢！怎么悔棋吖咩~",
                                  QMessageBox::Ok|QMessageBox::Cancel,QMessageBox::Ok);
            return;
        }
        //先在本地判断能否悔棋
        //使用return避免输出无效数据
        out << serverIP;
        break;
    }
    case refuse://拒绝悔棋
    {
        out << serverIP;
        break;
    }
    case allow://允许悔棋
    {
        out << serverIP;
        break;
    }
    case Restart://请求重新开始
    {
        out << serverIP;
        break;
    }
    case allowrestart://允许重新开始
    {
        out << serverIP;
        break;
    }
    case refuserestart://拒绝重新开始
    {
        out << serverIP;
        break;
    }
    }
    udpSocket->writeDatagram(data,data.length(),QHostAddress::Broadcast, 45455);//发送数据报

}

void MainWindow::newpoint(int x, int y) {//新下子的槽函数，调用sendMessage()函数
    sendMessage(NewPoint,x,y);
}


void MainWindow::on_pushButton_4_clicked()//退出按钮
{
    if(lan) {//如果局域网的话进行重新初始化操作，并发送离开消息
        sendMessage(Left,0,0);

        ClearBoard();
        ui->listWidget->clear();
        clear();

        IsRun=false;
        lan=false;

        ui->radioButton->setEnabled(1);
        ui->radioButton_2->setEnabled(1);
        //启用人机对战、人人对战按钮
        ui->pushButton_2->setEnabled(0);
        ui->pushButton->setEnabled(0);
        ui->pushButton_3->setText("开始");
        ui->pushButton->setText("暂停");

        ui->label->hide();
        ui->label_2->hide();
        ui->label_3->hide();
        //重新隐藏3个label
        ui->pushButton_4->setText("退出");
        update();
        return;
    }
    //如果是其他情况直接退出游戏
    this->close();
}
